package com.example.common.core;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.common.rc.aop.dicttrans.dictaop.NeedTransLate;
import com.example.common.util.Streams;
import com.example.common.util.auto_wrapper.AutoWhereUtil;
import com.example.common.util.util_entity.core.BaseEntity;
import io.swagger.annotations.ApiOperation;
import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import javax.validation.Valid;
import lombok.SneakyThrows;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * 基本控制器
 *
 * @author addzero
 * @since 2022/10/04
 */
@SuppressWarnings("all")
public class BaseController<S extends IService<PO>
    , C extends BaseConvert<ConditionInVO, InVO, OutVO, PO>
    , ConditionInVO
    , InVO
    , OutVO
    , PO extends BaseEntity> {

    @Autowired
    protected S service;

    @Autowired
    protected C convert;

    protected BaseService<S, C, ConditionInVO, InVO, OutVO, PO> baseService;

    @PostConstruct
    public void init() {
        baseService = BaseService.of(service, convert);
    }

    @ApiOperation("比较集合批量更新")
    @PostMapping(value = "compareBatchUpdate")
    @NeedTransLate
    public Result<Boolean> compareBatchUpdate(@RequestBody List<InVO> vos) {
        List<PO> pos = convert.vo2pos(vos);
        Class<PO> aClass = (Class<PO>) pos.stream().findAny().map(e -> e.getClass()).orElse(null);
        List<PO> collect = vos.stream().flatMap(e -> {
            LambdaQueryWrapper<PO> lambdaQueryWrapper1 = AutoWhereUtil.lambdaQueryByAnnotation(aClass, vos);
            //加了注解视为按若干个条件查出来的
            List<PO> list = service.list(lambdaQueryWrapper1);
            return list.stream();
        }).collect(Collectors.toList());
        //比较得到增删改集合
        Triple<List<PO>, List<PO>, List<PO>> compare = Streams.compare(pos, collect, PO::getId, PO::getId);
        List<PO> left = compare.getLeft();
        List<PO> middle = compare.getMiddle();
        List<PO> right = compare.getRight();
        boolean b = service.saveBatch(left);
        boolean b1 = service.removeBatchByIds(middle);
        boolean b2 = service.updateBatchById(right);
        return Result.OK(b && b1 && b2);
    }

    //唯一性条件确定Function
//    protected Function<InVO, LambdaQueryWrapper<PO>> uniqueConditionFun;

    //默认对ConditionInVO上加了注解的条件以及同名字段筛选
    //条件查询Fun
//    protected Function<ConditionInVO, LambdaQueryWrapper<PO>> conditionFun;

    @ApiOperation("列表查询-带条件")
    @PostMapping("/listByCondition")
    public Result<List<OutVO>> listConditionalQuery(@Valid @RequestBody ConditionInVO vo) {
        List<OutVO> outVOS = baseService.listConditionalQuery(vo);
        return Result.OK("查询成功", outVOS);
    }

    //    @ApiOperation("分页查询-jeecg生成器自带")
    @GetMapping(value = "/page")
    public Result<IPage<OutVO>> pageByJeecgCondition(ConditionInVO vo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        return Result.OK(baseService.page(vo, pageNo, pageSize));
    }

    @GetMapping("listAll")
    @ApiOperation("查询所有")
    @NeedTransLate
    public Result<List<OutVO>> listAll() {
        List<OutVO> outVOS = baseService.listAll();
        return Result.OK(outVOS);

    }

    @GetMapping("/queryById")
    @ApiOperation("根据id查询")
    public Result<OutVO> queryById(@RequestParam Serializable id) {
        OutVO outVO = baseService.queryById(id);
        return Result.OK(outVO);

    }

    @PostMapping("add")
    @ApiOperation("新增-单条")
    public Result<Boolean> add(@RequestBody InVO inVO) {
        boolean add = baseService.add(inVO);
        return Result.OK("新增成功", add);
    }

    @PostMapping("addIfAbsent")
//    @ApiOperation("新增-加唯一索引的新增")
    public Result<Boolean> addIfAbsent(@RequestBody InVO inVO) {
        boolean save = baseService.addIfAbsent(inVO);
        return Result.OK("新增成功", save);
    }

    @SneakyThrows
    //@RequestMapping(value = "/editIfAbsent", method = {RequestMethod.PUT, RequestMethod.POST})
    //@ApiOperation("edit-当给定条件不存在时修改")
    public Result<Boolean> editIfAbsent(@RequestBody InVO inVO) {
        boolean b = baseService.editIfAbsent(inVO);
        return Result.OK("修改成功", b);
    }

    @RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
    @ApiOperation("修改-单条")
    public Result<Boolean> edit(@RequestBody InVO inVO) {
        boolean edit = baseService.edit(inVO);
        return Result.OK("修改成功", edit);
    }

    @ApiOperation("删除-单条")
    @DeleteMapping(value = "/delete")
    public Result<Boolean> delete(@RequestParam Serializable id) {
        boolean data = service.removeById(id);
        return Result.OK("删除成功", data);
    }

    @DeleteMapping("deleteByIdList")
    @ApiOperation("delete-按id List<>批量删除")
    public Result<Boolean> deleteByIdList(@RequestParam List<Long> idList) {
        return Result.OK("批量删除成功", service.removeByIds(idList));
    }
}
